package com.photoeditor.demo.model.image.tools;

import android.graphics.Matrix;
import android.view.animation.Animation;
import android.view.animation.Transformation;


/**
 * 一种用于控制矩阵变换过渡的动画。该动画实现在指定时间段内，两个矩阵的平滑过渡效果。
 */
public class MatrixAnimation extends Animation {
    private Matrix mFromMatrix = new Matrix();  // 原始矩阵
    private Matrix mToMatrix = new Matrix();    // 目标矩阵
    
    // 以下的变量是为了提高性能，提前缓存的矩阵值
    private float[] mFromValues = new float[9];
    private float[] mToValues = new float[9];
    private float[] mTempValues = new float[9]; // 中间过程的矩阵值
    
    /**
     * 构造一个矩阵变换过渡的动画
     * @param from 矩阵变换的原始矩阵对象，不可以为空
     * @param to 矩阵变换的目标矩阵对象，不可以为空
     * @throws IllegalArgumentException 如果原始矩阵或目标矩阵对象为空
     */
    public MatrixAnimation(Matrix from, Matrix to) {
        if(from == null) {
            throw new IllegalArgumentException("Argument 'from' can not be null!");
        }
        if(to == null) {
            throw new IllegalArgumentException("Argument 'to' can not be null!");
        }
        
        mFromMatrix.set(from);
        mFromMatrix.getValues(mFromValues);
        mFromMatrix.getValues(mTempValues);
        
        mToMatrix.set(to);
        mToMatrix.getValues(mToValues);
    }
    
    /**
     * 设置矩阵变换的原始矩阵对象
     * @param matrix 矩阵变换的原始矩阵对象
     */
    public void setFromMatrix(Matrix matrix) {
        mFromMatrix.set(matrix);
        mFromMatrix.getValues(mFromValues);
        mFromMatrix.getValues(mTempValues);
    }
    
    /**
     * 设置矩阵变换的目标矩阵对象
     * @param matrix 矩阵变换的目标矩阵对象
     */
    public void setToMatrix(Matrix matrix) {
        mToMatrix.set(matrix);
        mToMatrix.getValues(mToValues);
    }
 
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        if(t == null) return;
        
        float currFromValue, currToValue;
        for (int i = 0; i < 9; i++) {
            currFromValue = mFromValues[i];
            currToValue = mToValues[i];
            if(currFromValue != currToValue) {
                mTempValues[i] = currFromValue + (currToValue - currFromValue) * interpolatedTime;
            }
        }
        
        t.getMatrix().setValues(mTempValues);
    }

    @Override
    public boolean willChangeTransformationMatrix() {
        return true;
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
}
